
#pragma once

#include "SubSystemInfo.h"

using namespace System::ComponentModel;
using namespace System::Collections::Generic;

namespace ttg_internal
{
	namespace utils
	{
		///<summary>
		///Contains information and statistics about one computing device.
		///</summary>
		public ref class DeviceInfo : public INotifyPropertyChanged,
									  public System::ICloneable
		{
			private:
				BindingList<SubSystemInfo ^> ^_subSystems;
				System::String ^_name;
				System::String ^_description;
				System::String ^_unitName;
				double _usage;
				double _maxValue;
				///<summary>
				/// Notifies about updated property.
				///</summary>
				void NotifyPropertyChanged(System::String ^info)
				{
					PropertyChanged(this, gcnew PropertyChangedEventArgs(info));
				}
			internal:
				DeviceInfo(System::String ^name,
						   System::String ^description,
						   System::String ^unitName,
						   double maxValue)
				{
					_subSystems = gcnew BindingList<SubSystemInfo ^>();
					_name = name;
					_description = description;
					_unitName = unitName;
					_usage = 0.0;
					_maxValue = maxValue;
				}
				///<summary>
				/// Returns information of subsystem with given name (or nullptr).
				///<summary>
				SubSystemInfo ^GetSubSystemInfo(System::String ^name)
				{
					for each (SubSystemInfo ^ss in _subSystems)
						if (ss->Name == name)
							return ss;
					return nullptr;
				}
				///<summary>
				/// Registeres given subsystem.
				///</summary>
				void AddSubSystem(SubSystemInfo ^info)
				{
					_subSystems->Add(info);
				}
			public:
				///<summary>
				/// Event for INotifyPropertChanged.
				///</summary>
				virtual event PropertyChangedEventHandler ^PropertyChanged;
				///<summary>
				/// Returns normalized usage of current device (from 0.0 to 1.0).
				///</summary>
				property double Usage
				{
					double get()
					{ return _usage; }
					void set(double value)
					{
						NotifyPropertyChanged("Usage");
						_usage = value;
					}
				}
				///<summary>
				/// Returns maximal achievable value (that is equal to usage == 1.0).
				///<summary>
				property double MaxValue
				{
					double get()
					{ return _maxValue; }
				}
				///<summary>
				/// Returns name of current device (e.g. "CPU", "GPU", etc).
				///</summary>
				property System::String ^Name
				{
					System::String ^get()
					{ return _name; }
				}
				///<summary>
				/// Returns name of measuring unit (e.g. "%", "MB", etc).
				///<summary>
				property System::String ^UnitName
				{
					System::String ^get()
					{ return _unitName; }
				}
				///<summary>
				/// Returns description of the current device (in user-suitable form).
				///<summary>
				property System::String ^Description
				{
					System::String ^get()
					{ return _description; }
				}
				///<summary>
				/// Returns collection of dependent subsystem.
				///</summary>
				property BindingList<SubSystemInfo ^> ^SubSystems
				{
					BindingList<SubSystemInfo ^> ^get()
					{ return _subSystems; }
				}
				virtual Object ^Clone()
				{
					DeviceInfo ^di = gcnew DeviceInfo(Name, Description, UnitName, MaxValue);
					di->Usage = Usage;
					for each (SubSystemInfo ^ss in SubSystems)
						di->AddSubSystem((SubSystemInfo ^)ss->Clone());
					return di;
				}
		};
	}
}
